package com.antaohua.tools.framework.base.dao;

import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.persistence.criteria.CriteriaDelete;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.CriteriaUpdate;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.query.Query;
import org.springframework.beans.factory.annotation.Autowired;

import com.antaohua.tools.framework.base.exception.DeleteEntityException;
import com.antaohua.tools.framework.base.exception.InsertEntityException;
import com.antaohua.tools.framework.base.exception.QureyEntityException;
import com.antaohua.tools.framework.base.exception.UpdateEntityException;
import com.antaohua.tools.framework.base.interfase.BaseDaoInterface;
import com.antaohua.tools.framework.base.interfase.CreateDateInterfase;
import com.antaohua.tools.framework.base.interfase.DeleteStateInterfase;
import com.antaohua.tools.framework.base.interfase.UpdateDateInterfase;
import com.antaohua.tools.framework.base.model.UUIDIdentityModel;
import com.antaohua.tools.framework.base.utils.PageUtil;

public abstract class BaseDao<E extends UUIDIdentityModel> implements BaseDaoInterface<E>{

	private static Log log = LogFactory.getLog(BaseDao.class);

//	@Autowired

//	protected LocalSessionFactoryBean sessionFactoryBean;

	@Autowired
	private SessionFactory sessionFactory;

	protected abstract Class<E> getEntityClass();

	public final Session getSession() {
		Session session = null;
		try {
			session = this.sessionFactory.getCurrentSession();
		} catch (HibernateException e) {
			log.error("Spring未打开Sesson 查看Service 中@Transactional 是否正确！");
			throw new NullPointerException(
					"Spring未打开Sesson 查看Service 中@Transactional 是否正确！");
		}
		return session;
	}

	@SuppressWarnings("rawtypes")
	public Query getQuery(String queryString) {
		return getSession().createQuery(queryString);
	}
	
	public <T> Query<T> getQuery(String queryString, Class<T> resultType) {
		return getSession().createQuery(queryString,resultType);
	}
	public Query<E> getQuery(CriteriaQuery<E> criteriaQuery) {
		return getSession().createQuery(criteriaQuery);
	}

	
	

	public E save(E entity) throws InsertEntityException{
		if ((entity instanceof CreateDateInterfase)) {
			((CreateDateInterfase) entity).setCreateDate(new Date());
		}
		if ((entity instanceof DeleteStateInterfase)) {
			((DeleteStateInterfase) entity).setDeletedState(DeleteStateInterfase.DELETE_TRUE);
		}
		try {
			getSession().save(entity);
		} catch (Exception e) {
			log.error(e);
			throw new InsertEntityException(e.getMessage());
		}
		
		
		return entity;
	}
	public List<E> save(List<E> entitys) throws InsertEntityException{
		for (E entity : entitys) {
			save(entity);
		}
		return entitys;
	}
	

	public E update(E entity) throws UpdateEntityException{
		if ((entity instanceof UpdateDateInterfase)) {
			UpdateDateInterfase updateDateEntity = (UpdateDateInterfase) entity;
			updateDateEntity.setUpdateDate(new Date());
		}
		try {
			getSession().update(entity);
		} catch (Exception e) {
			log.error(e);
			throw new UpdateEntityException(e.getMessage());
		}
		return entity;
	}
	
	public List<E> update(List<E> entitys)throws UpdateEntityException{
		for (E entity : entitys) {
			update(entity);
		}
		return entitys;
	}
	
	
	public void delete(E entity) throws DeleteEntityException{
		if ((entity instanceof DeleteStateInterfase)) {
			DeleteStateInterfase deleteEntity = (DeleteStateInterfase) entity;
			deleteEntity.setDeletedState(DeleteStateInterfase.DELETE_FALSE);
			if ((entity instanceof UpdateDateInterfase)) {
				UpdateDateInterfase updateDateEntity = (UpdateDateInterfase) entity;
				updateDateEntity.setUpdateDate(new Date());
			}
			try {
				getSession().update(entity);
			} catch (Exception e) {
				log.error(e);
				throw new DeleteEntityException(e.getMessage());
			}
			
		} else {
			try {
				getSession().delete(entity);
			} catch (Exception e) {
				throw new DeleteEntityException(e.getMessage());
			}
		}
	}

	public Integer deleteById(String id) throws DeleteEntityException{
		try {
			if ((getEntityClass().isAssignableFrom(DeleteStateInterfase.class))){
				StringBuffer hql = new StringBuffer("UPDATE ").append(getEntityClass().getSimpleName()).append(" entity ").append(" SET ").append(" entity.").append(DeleteStateInterfase.DELTET_ATTRIBUTE_NAME).append(" = ").append(DeleteStateInterfase.DELETE_TRUE).append(" WHERE entity.ID = :id");
				Query<E> qurey = getQuery(hql.toString(),getEntityClass());
				qurey.setParameter("id", id);
				return qurey.executeUpdate();
			}else{
				StringBuffer hql = new StringBuffer("Delete FROM ").append(getEntityClass().getSimpleName()).append(" WHERE ID = :id");
				Query<E> qurey = getQuery(hql.toString(),getEntityClass());
				qurey.setParameter("id", id);
				return qurey.executeUpdate();
			}
		} catch (Exception e) {
			log.error(e);
			throw new DeleteEntityException(e.getMessage());
		}
	}

	public Integer deleteByIds(List<String> ids) throws DeleteEntityException{
		try {
			if ((getEntityClass().isAssignableFrom(DeleteStateInterfase.class))){
				StringBuffer hql = new StringBuffer("UPDATE ").append(getEntityClass().getSimpleName()).append(" entity ").append(" SET ").append(" entity.").append(DeleteStateInterfase.DELTET_ATTRIBUTE_NAME).append(" = ").append(DeleteStateInterfase.DELETE_TRUE).append(" WHERE entity.ID = :ids");
				Query<E> qurey = getQuery(hql.toString(),getEntityClass());
				qurey.setParameterList("ids", ids);
				return qurey.executeUpdate();
			}else{
				StringBuffer hql = new StringBuffer("Delete FROM ").append(getEntityClass().getSimpleName()).append(" WHERE ID = :ids");
				Query<E> qurey = getQuery(hql.toString(),getEntityClass());
				qurey.setParameterList("ids", ids);
				return qurey.executeUpdate();
			}
		} catch (Exception e) {
			log.error(e);
			throw new DeleteEntityException(e.getMessage());
		}
	}

	

	
	public Integer deleteByProperty(Map<String, Object> propertys) throws DeleteEntityException{
		try {
			if ((getEntityClass().isAssignableFrom(DeleteStateInterfase.class))){
				StringBuffer hql = new StringBuffer("UPDATE ").append(getEntityClass().getSimpleName()).append(" entity ").append(" SET ").append(" entity.").append(DeleteStateInterfase.DELTET_ATTRIBUTE_NAME).append(" = ").append(DeleteStateInterfase.DELETE_TRUE).append(" WHERE 1=1 ");
				for (Map.Entry<String, Object> property : propertys.entrySet()){
					if(property.getValue()!=null){
						hql.append(" AND ").append(property.getKey()).append(" =:").append(property.getKey());
					}else{
						hql.append(" AND ").append(property.getKey()).append(" IS NULL ");
					}
					
				}
				Query<E> qurey = getQuery(hql.toString(),getEntityClass());
				for (Map.Entry<String, Object> property : propertys.entrySet()){
					if(property.getValue()!=null){
						qurey.setParameter(property.getKey(),property.getValue());
					}
				}
				return qurey.executeUpdate();
			}else{
				StringBuffer hql = new StringBuffer("Delete FROM ").append(getEntityClass().getSimpleName()).append(" WHERE 1=1 ");
				for (String propertyName : propertys.keySet()){
					hql.append(" AND ").append(propertyName).append(" =:").append(propertyName);
				}
				Query<E> qurey = getQuery(hql.toString(),getEntityClass());
				for (Map.Entry<String, Object> property : propertys.entrySet()){
					if(property.getValue()!=null){
						qurey.setParameter(property.getKey(),property.getValue());
					}
				}
				return qurey.executeUpdate();
			}
		} catch (Exception e) {
			log.error(e);
			throw new DeleteEntityException(e.getMessage());
		}
	}
	
	public Integer deleteByProperty(String propertyName,Object propertyValue) throws DeleteEntityException{
		try {
			if ((getEntityClass().isAssignableFrom(DeleteStateInterfase.class))){
				StringBuffer hql = new StringBuffer("UPDATE ").append(getEntityClass().getSimpleName()).append(" entity ").append(" SET ").append(" entity.").append(DeleteStateInterfase.DELTET_ATTRIBUTE_NAME).append(" = ").append(DeleteStateInterfase.DELETE_TRUE).append(" WHERE 1=1 ");
				if(propertyValue!=null){
					hql.append(" AND ").append(propertyName).append(" =:").append(propertyName);
				}else{
					hql.append(" AND ").append(propertyName).append(" IS NULL ");
				}
				Query<E> qurey = getQuery(hql.toString(),getEntityClass());
				if(propertyValue!=null){
					qurey.setParameter(propertyName,propertyValue);
				}
				return qurey.executeUpdate();
			}else{
				StringBuffer hql = new StringBuffer("Delete FROM ").append(getEntityClass().getSimpleName()).append(" WHERE 1=1 ");
				if(propertyValue!=null){
					hql.append(" AND ").append(propertyName).append(" =:").append(propertyName);
				}else{
					hql.append(" AND ").append(propertyName).append(" IS NULL ");
				}
				Query<E> qurey = getQuery(hql.toString(),getEntityClass());
				if(propertyValue!=null){
					qurey.setParameter(propertyName,propertyValue);
				}
				return qurey.executeUpdate();
			}
		} catch (Exception e) {
			log.error(e);
			throw new DeleteEntityException(e.getMessage());
		}
	}
	
	
	
	
	
	
	
	
	

	public E findById(String id) throws QureyEntityException {
		try {
			E entity = getSession().get(getEntityClass(), id);
			if(isDeleteStateInterfase()){
				if(DeleteStateInterfase.DELETE_FALSE.equals(((DeleteStateInterfase)entity).getDeletedState())){
					return entity;
				}else{
					return null;
				}
			}else{
				return entity;
			}
			
		} catch (Exception e) {
			log.error(e);
			throw new QureyEntityException(e.getMessage());
		}
		
	}
	
	
	public List<E> findByIds(List<String> ids) throws QureyEntityException {
		try {
			StringBuffer hql = new StringBuffer("FROM ");
			hql.append(getEntityClass().getSimpleName());
			if(isDeleteStateInterfase()){
				hql.append(" WHERE ").append(DeleteStateInterfase.DELTET_ATTRIBUTE_NAME).append(" = ").append(DeleteStateInterfase.DELETE_FALSE);
			}
			Query<E> query = getQuery(hql.toString(), getEntityClass());
			return query.list();
		} catch (Exception e) {
			log.error(e);
			throw new QureyEntityException(e.getMessage());
		}
	}
	
	public PageUtil<E> findAll(PageUtil<E> page) throws QureyEntityException {
		
		String hql = "FROM "+getEntityClass().getSimpleName();
		if(isDeleteStateInterfase()){
			hql += " Where "+DeleteStateInterfase.DELTET_ATTRIBUTE_NAME+" = "+DeleteStateInterfase.DELETE_FALSE;
		}
		Query<E> qurey = getQuery(hql,getEntityClass());
		qurey.setFirstResult(page.getFirstNumber());
		qurey.setMaxResults(page.getLimit().intValue());
		List<E> list = null;
		try {
			list = qurey.list();
		} catch (Exception e) {
			log.error(e);
			throw new QureyEntityException(e.getMessage());
		}
		page.getRoot().addAll(list);
		page.setTotal(countAll());
		return page;
	}

	public List<E> findAll() throws QureyEntityException {
		String hql = "FROM "+getEntityClass().getSimpleName();
		
		if(isDeleteStateInterfase()){
			hql += " Where "+DeleteStateInterfase.DELTET_ATTRIBUTE_NAME+" = "+DeleteStateInterfase.DELETE_FALSE;
		}
		Query<E> qurey = getQuery(hql,getEntityClass());
		try {
			return qurey.list();
		} catch (Exception e) {
			log.error(e);
			throw new QureyEntityException(e.getMessage());
		}
	}

	public List<E> findByProperty(String propertyName, Object value) throws QureyEntityException {
		try {
			StringBuffer hql = new StringBuffer("FROM ");
			hql.append(getEntityClass().getSimpleName()).append(" where 1=1");
			hql.append(" and ");
			
			if (value == null) {
				hql.append(propertyName).append(" is null");
			} else {
				hql.append(propertyName).append(" = ").append(":").append(propertyName);
			}
			
			if(isDeleteStateInterfase()){
				hql.append(" and ").append(DeleteStateInterfase.DELTET_ATTRIBUTE_NAME).append(" = ").append(DeleteStateInterfase.DELETE_FALSE);
			}
			Query<E> qurey = getQuery(hql.toString(),getEntityClass());
			if (value != null){
				qurey.setParameter(propertyName, value);
			}
			return qurey.list();
		} catch (Exception e) {
			log.error(e);
			throw new QureyEntityException(e.getMessage());
		}
	}

	
	public List<E> findByProperty(Map<String, Object> propertys) throws QureyEntityException {
		try {
			if ((propertys == null) || (propertys.size() == 0)) {
				return findAll();
			}
			StringBuffer hql = new StringBuffer("FROM ");
			hql.append(getEntityClass().getSimpleName()).append(" AS P ").append(" WHERE 1=1");
			if(isDeleteStateInterfase()){
				hql.append(" AND ").append(DeleteStateInterfase.DELTET_ATTRIBUTE_NAME).append(" = ").append(DeleteStateInterfase.DELETE_FALSE);
			}
			for (Map.Entry<String, Object> property : propertys.entrySet()) {
				if ((property.getKey() != null) && (!((String) property.getKey()).trim().equals(""))) {
					hql.append(" AND ");
					
					if (property.getValue() == null) {
						hql.append("P.").append(property.getKey()).append(" IS NULL ");
					} else {
						hql.append("P.").append(property.getKey()).append("=").append(":").append(property.getKey());
					}
				}
			}
			Query<E> qurey = getQuery(hql.toString(),getEntityClass());
			for (Map.Entry<String, Object> property : propertys.entrySet()){
				if(property.getValue() != null){
					qurey.setParameter(property.getKey(), property.getValue());
				}
			}
			return qurey.list();
		} catch (Exception e) {
			e.printStackTrace();
			log.error(e);
			throw new QureyEntityException(e.getMessage());
		}
	}

	
	
	
	
	public Long countByProperty(String propertyName, Object value) throws QureyEntityException {
		try {
			StringBuffer hql = new StringBuffer("select count(*) FROM ");
			hql.append(getEntityClass().getSimpleName()).append(" where 1=1 ");
			if (value == null) {
				hql.append(" and ").append(propertyName).append(" is null ");
			} else {
				hql.append(" and ").append(propertyName).append(" = ").append(":").append(propertyName);
			}
			if(isDeleteStateInterfase()){
				hql.append(" and ").append(DeleteStateInterfase.DELTET_ATTRIBUTE_NAME).append(" = ").append(DeleteStateInterfase.DELETE_FALSE);
			}
			System.out.println(hql);
			Query<Long> qurey = getQuery(hql.toString(),Long.class);
			qurey.setParameter(propertyName,value);
			return qurey.uniqueResult();
		} catch (Exception e) {
			log.error(e);
			throw new QureyEntityException(e.getMessage());
		}
	}
	
	public Long countByProperty(Map<String, Object> propertys) throws QureyEntityException {
		try {
			StringBuffer hql = new StringBuffer("select count(*) FROM ");
			hql.append(getEntityClass().getSimpleName()).append(" where 1=1 ");
			for (Map.Entry<String, Object> property : propertys.entrySet()){
				if (property.getValue() == null) {
					hql.append(" and ").append(property.getKey()).append(" is null ");
				} else {
					hql.append(" and ").append(property.getKey()).append(" = ").append(":").append(property.getKey());
				}
			}
			
			
			if(isDeleteStateInterfase()){
				hql.append(" and ").append(DeleteStateInterfase.DELTET_ATTRIBUTE_NAME).append(" = ").append(DeleteStateInterfase.DELETE_FALSE);
			}
			Query<Long> qurey = getQuery(hql.toString(),Long.class);
			for (Map.Entry<String, Object> property : propertys.entrySet()){
				if(property.getValue() != null){
					qurey.setParameter(property.getKey(), property.getValue());
				}
			}
			return qurey.uniqueResult();
		} catch (Exception e) {
			log.error(e);
			throw new QureyEntityException(e.getMessage());
		}
	}


	public Long countAll()  throws QureyEntityException {
		
		StringBuffer hql = new StringBuffer("select count(*) FROM ");
		hql.append(getEntityClass().getSimpleName()).append(" where 1=1");
		
		if(isDeleteStateInterfase()){
			hql.append(" and ").append(DeleteStateInterfase.DELTET_ATTRIBUTE_NAME).append(" = ").append(DeleteStateInterfase.DELETE_FALSE);
		}
		Query<Long> qurey = getQuery(hql.toString(),Long.class);
		
		return qurey.uniqueResult();
	}

	

	

	
	public Boolean isExistence(String propertyName, Object value)  throws QureyEntityException {
		StringBuffer hql = new StringBuffer("select count(*) FROM ");
		hql.append(getEntityClass().getSimpleName()).append(" where 1=1 ");
		if (value == null) {
			hql.append(propertyName).append(" is null ");
		} else {
			hql.append(propertyName).append("=").append(":").append(value);
		}
		if(isDeleteStateInterfase()){
			hql.append(" and ").append(DeleteStateInterfase.DELTET_ATTRIBUTE_NAME).append(" = ").append(DeleteStateInterfase.DELETE_FALSE);
		}
		Query<E> qurey = getQuery(hql.toString(),getEntityClass());
		if(Integer.valueOf(qurey.uniqueResult().toString())>0){
			return Boolean.valueOf(false);
		}else{
			return Boolean.valueOf(true);
		}
	}

	

	public boolean isDeleteStateInterfase() {
		return DeleteStateInterfase.class.isAssignableFrom(getEntityClass());
	}

	public boolean isDeleteStateInterfase(Class<?> classz) {
		return DeleteStateInterfase.class.isAssignableFrom(classz);
	}


	
	
	
	
	
	
	
	
	
	
}
